package com.zzyl.service.impl;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.zzyl.base.PageResponse;
import com.zzyl.dto.NursingProjectDto;
import com.zzyl.entity.NursingProject;
import com.zzyl.entity.NursingProjectPlan;
import com.zzyl.enums.BasicEnum;
import com.zzyl.exception.BaseException;
import com.zzyl.mapper.NursingProjectMapper;
import com.zzyl.mapper.NursingProjectPlanMapper;
import com.zzyl.mapper.UserMapper;
import com.zzyl.service.NursingProjectService;
import com.zzyl.vo.NursingProjectVo;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

/**
 * 护理项目Service实现类
 */
@Service
public class NursingProjectServiceImpl implements NursingProjectService {

    private final NursingProjectMapper nursingProjectMapper;
    private final UserMapper userMapper;
    private final NursingProjectPlanMapper nursingProjectPlanMapper;

    public NursingProjectServiceImpl(NursingProjectMapper nursingProjectMapper, UserMapper userMapper, NursingProjectPlanMapper nursingProjectPlanMapper) {
        this.nursingProjectMapper = nursingProjectMapper;
        this.userMapper = userMapper;
        this.nursingProjectPlanMapper = nursingProjectPlanMapper;
    }

    @Override
    public PageResponse<NursingProjectVo> getByPage(String name, Integer status, Integer pageNum, Integer pageSize) {

        // 开启分页查询
        Page<NursingProjectVo> NursingProjectPage =
                PageHelper.startPage(pageNum, pageSize).doSelectPage(() ->
                        // 在护理项目数据库中查询到的结果返回的对象其实是<NursingProject>(entity)，而在这里，我们直接用VO来接受
                        // 是因为VO和entity中的属性是一样的... 我才发现
                        nursingProjectMapper.selectByPage(name, status));

        // 护理项目的创建人姓名需要去user数据库中查询
        NursingProjectPage.getResult().forEach(nursingProjectVo -> {
            try {
                String realName = userMapper.selectByPrimaryKey(nursingProjectVo.getCreateBy()).getRealName();
                nursingProjectVo.setCreator(realName);
            } catch (NullPointerException e) {
                nursingProjectVo.setCreator("Unknown Creator");
            }
        });
        // 将查询的结果<Page>对象，转换成PageResponse对象
        return PageResponse.of(NursingProjectPage, NursingProjectVo.class);

        // 在护理项目(entity)数据库中，是没有creator(创建人姓名)，只有creatBy字段
        // 现在前端需要拿到creator，我们需要在user数据库中找到
        // 本项目的entity，Vo，Dto 都继承了base，很多属性都有了，就不需要针对某一个业务频繁创建很多VO对象
    }

    // 新增护理项目
    @Override
    public int insertProject(NursingProjectDto dto) {
        // 1.校验参数
        // ObjectUtil.isEmpty(字符串) Objects.isNull(基本数据类型)
        // ？？前端为什么要把id传过来？在np里面id主键是自增的，在sql里面也不需要写
        if (ObjectUtils.isEmpty(dto.getImage()) || ObjectUtils.isEmpty(dto.getName()) || ObjectUtils.isEmpty(dto.getNursingRequirement()) || ObjectUtils.isEmpty(dto.getRemark()) || ObjectUtils.isEmpty(dto.getUnit()) ||
                Objects.isNull(dto.getId()) || Objects.isNull(dto.getOrderNo()) || Objects.isNull(dto.getPrice()) || Objects.isNull(dto.getStatus())) {
            throw new BaseException(BasicEnum.PARAM_IS_NULL);
        }
        // 2.业务处理
        // 护理项目的名称不能重复
        NursingProject nursingProjectDB = nursingProjectMapper.selectByName(dto.getName());
        if (Objects.nonNull(nursingProjectDB)) {
            throw new BaseException(BasicEnum.NAME_IS_EXIST);
        }
        // 补全实体
        NursingProject nursingProject = new NursingProject();
        BeanUtils.copyProperties(dto, nursingProject);

        nursingProject.setCreateTime(LocalDateTime.now());
        nursingProject.setUpdateTime(LocalDateTime.now());
        nursingProject.setCreateBy(1L);
        nursingProject.setUpdateBy(1L);

        // 3.封装数据
        return nursingProjectMapper.insert(nursingProject);

    }

    // 根据id查询护理项目
    @Override
    public NursingProjectVo selectById(Long id) {
        NursingProject nursingProject = nursingProjectMapper.selectById(id);
        if (Objects.isNull(nursingProject)) {
            throw new BaseException(BasicEnum.ID_NO_EXIST);
        }
        // 封装数据
        NursingProjectVo nursingProjectVo = new NursingProjectVo();
        BeanUtils.copyProperties(nursingProject, nursingProjectVo);
        return nursingProjectVo;
    }

    // 修改护理项目
    @Override
    public int updateProject(NursingProjectDto dto) {
        // 1.校验参数
        // 省略

        // 2.业务处理
        // 【判断1】通过id查找该护理项目是否存在
        NursingProject nursingProjectDB = nursingProjectMapper.selectById(dto.getId());
        if (Objects.isNull(nursingProjectDB)) {
            throw new BaseException(BasicEnum.ID_NO_EXIST);
        }
        // 【判断2】判断该项目是否和护理计划绑定
        NursingProjectPlan nursingProjectPlanDB = nursingProjectPlanMapper.selectByProjectId(dto.getId());
        if (Objects.nonNull(nursingProjectPlanDB)) {
            throw new BaseException(BasicEnum.PROJECT_IS_BIND);
        }

        // 封装数据
        NursingProject nursingProject = new NursingProject();
        BeanUtils.copyProperties(dto, nursingProject);

        nursingProject.setUpdateTime(LocalDateTime.now());
        nursingProject.setUpdateBy(1L);

        // 动态更新项目(只更新前端传过来的数据，和我们添加的更新时间和更新人)
        try {
            return nursingProjectMapper.updateById(nursingProject);
        } catch (Exception e) {
            // name字段不能重复，交给数据库去做
            throw new BaseException(BasicEnum.NAME_IS_EXIST);
        }

    }

    // 修改护理项目状态
    @Override
    public int updateStatus(Long id, Integer status) {
        // 1.校验参数
        if (Objects.isNull(id) || Objects.isNull(status)) {
            throw new BaseException(BasicEnum.PARAM_IS_NULL);
        }
        // 2.业务处理
        // 通过id查找该护理项目是否存在
        NursingProject nursingProjectDB = nursingProjectMapper.selectById(id);
        if (Objects.isNull(nursingProjectDB)) {
            throw new BaseException(BasicEnum.ID_NO_EXIST);
        }
        // 【判断2】判断该项目是否和护理计划绑定
        NursingProjectPlan nursingProjectPlanDB = nursingProjectPlanMapper.selectByProjectId(id);
        if (Objects.nonNull(nursingProjectPlanDB)) {
            throw new BaseException(BasicEnum.PROJECT_IS_BIND);
        }

        return nursingProjectMapper.updateStatusById(id, status);
    }

    // 删除护理项目
    @Override
    public int deleteById(Long id) {
        // 1.校验参数
        if (Objects.isNull(id)) {
            throw new BaseException(BasicEnum.PARAM_IS_NULL);
        }
        // 2.业务处理
        // 通过id查找该护理项目是否存在
        NursingProject nursingProjectDB = nursingProjectMapper.selectById(id);
        if (Objects.isNull(nursingProjectDB)) {
            throw new BaseException(BasicEnum.ID_NO_EXIST);
        }
        // 【判断2】判断该项目是否和护理计划绑定
        NursingProjectPlan nursingProjectPlanDB = nursingProjectPlanMapper.selectByProjectId(id);
        if (Objects.nonNull(nursingProjectPlanDB)) {
            throw new BaseException(BasicEnum.PROJECT_IS_BIND);
        }
        return nursingProjectMapper.deleteById(id);
    }

    // 查询所有护理项目
    @Override
    public List<NursingProjectVo> selectAll() {
        List<NursingProjectVo> voList = new ArrayList<>();
        List<NursingProject> nursingProjectList = nursingProjectMapper.selectAll();

        // 遍历nursingProjectList，将nursingProject转换为vo，并添加到voList中
        nursingProjectList.forEach(nursingProject -> {
                    NursingProjectVo vo = new NursingProjectVo();
                    BeanUtils.copyProperties(nursingProject, vo);
                    // 给vo的creator属性赋值
                    try {
                        String realName = userMapper.selectByPrimaryKey(vo.getCreateBy()).getRealName();
                        vo.setCreator(realName);
                    } catch (NullPointerException e) {
                        vo.setCreator("Unknown Creator");
                    }
                    // 将vo添加到voList
                    voList.add(vo);
                }
        );
        return voList;
    }


}